﻿/// <reference path="Interpolaters.js" />
/*
    Name:           Simplex Noise
    Description:
                    This library provides the implementation
                    of Ken Perlin's Simplex Noise function direct
                    from Ken's implemention in appendix B
                    http://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf
    Date: 2014/02/07
    Version: 0.0.1
    Author: Dave Russell 
*/
SimplexNoise = new function () {
    var i,j,k;
    var A = [0,0,0];
    var u,v,w;

    var T = [0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a];

    this.Get1D = function (x) {
        return this.noise(x, 0, 0);
    };

    this.Get2D = function (x, y) {
        return this.noise(x, y, 0);
    };

    this.noise = function(x,y,z){
        var s = (x+y+z)/3;
        i= parseInt(Math.floor(x+s)); 
        j=parseInt(Math.floor(y+s));
        k=parseInt(Math.floor(z+s));
        s = (i + j + k) / 6.;
        u = x - i + s;
        v = y - j + s;
        w = z - k + s;

        A[0]=A[1]=A[2]=0;
        var hi = u>=w ? u>=v ? 0 : 1 : v>=w ? 1 : 2;
        var lo = u< w ? u< v ? 0 : 1 : v< w ? 1 : 2;
        return this.K(hi) + this.K(3-hi-lo) + this.K(lo) + this.K(0);
    };

    this.K = function(a) {
        var s = (A[0]+A[1]+A[2])/6.;
        var x = u - A[0] + s,
            y = v - A[1] + s,
            z = w - A[2] + s;
        var t = .6 - x * x - y * y - z * z;
        var h = this.shuffle(i + A[0], j + A[1], k + A[2]);

        A[a]++;

        if (t < 0) {
            return 0;
        }

        // calculate the gradients
        var b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
        var p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
        p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
        t *= t;
        return 8 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
    };

    this.shuffle = function(i, j, k) {
        return this.b4Param(i, j, k, 0) + this.b4Param(j, k, i, 1) + this.b4Param(k, i, j, 2) + this.b4Param(i, j, k, 3) +
        this.b4Param(j, k, i, 4) + this.b4Param(k, i, j, 5) + this.b4Param(i, j, k, 6) + this.b4Param(j, k, i, 7);
    };

    this.b4Param = function (i, j, k, B) { return T[this.b2Param(i, B) << 2 | this.b2Param(j, B) << 1 | this.b2Param(k, B)]; };
    
    this.b2Param = function (N, B) { return N >> B & 1; };

};




   

